home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume11 / tinymud2 / xenix_di.ffs < prev   
Encoding:
Internet Message Format  |  1990-08-10  |  43.8 KB

  1. Path: uunet!zephyr.ens.tek.com!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v11i021:  tinymud2 - user-extendible multi-user adventure (v1.5.4), xenix_diffs
  5. Message-ID: <6123@tekred.CNA.TEK.COM>
  6. Date: 10 Aug 90 00:03:29 GMT
  7. Sender: news@tekred.CNA.TEK.COM
  8. Lines: 1764
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Stu Heiss <stu@jpusa1.chi.il.us>
  12. Posting-number: Volume 11, Issue 21
  13. Archive-name: tinymud2/xenix_diffs
  14. Patch-To: tinymud2: Volume 11, Issue 5-14
  15.  
  16.     [Not runnning Xenix, I haven't tried these patches.... -br]
  17.  
  18. [[Attached below is what's needed to bring up tinymud on xenix using
  19. fifos instead of sockets for server/client communication.  The bulk
  20. of this is fifoiface.c which replaces oldinterface.c.  There are
  21. some minor diffs to game.c, Makefile, and a few missing routines.
  22. A startup for the server is included as well as a client which is
  23. a small shell script.  You are, of course, limmited to one machine,
  24. but you can have a number of people playing.  Have fun.]]
  25.  
  26. #! /bin/sh
  27. # This is a shell archive, meaning:
  28. # 1. Remove everything above the #! /bin/sh line.
  29. # 2. Save the resulting text in a file.
  30. # 3. Execute the file with /bin/sh (not csh) to create:
  31. #    xenix.diffs
  32. #    rename.c
  33. #    index.c
  34. #    random.c
  35. #    fifoiface.c
  36. #    tinymud.sh
  37. #    restart
  38. # This archive created: Wed Aug  8 14:51:35 1990
  39. # By:    stu (JPUSA - Chicago, IL)
  40. export PATH; PATH=/bin:/usr/bin:$PATH
  41. echo shar: "extracting 'xenix.diffs'" '(7297 characters)'
  42. if test -f 'xenix.diffs'
  43. then
  44.     echo shar: "will not over-write existing file 'xenix.diffs'"
  45. else
  46. sed 's/^X//' << \SHAR_EOFxenix.diffs > 'xenix.diffs'
  47. XRCS file: RCS/Makefile,v
  48. Xretrieving revision 1.1
  49. Xdiff -c -r1.1 Makefile
  50. X*** /tmp/,RCSt1a08638    Wed Aug  8 14:48:47 1990
  51. X--- Makefile    Wed Aug  8 14:46:29 1990
  52. X***************
  53. X*** 8,15
  54. X  #
  55. X  
  56. X  # GCC:
  57. X! #CC=gcc
  58. X! #OPTIM= -g -W -Wreturn-type -Wunused -Wcomment -Wwrite-strings
  59. X  
  60. X  # Systems with 'cc' built from GCC (IBM RT, NeXT):
  61. X  CC=cc
  62. X
  63. X--- 8,16 -----
  64. X  #
  65. X  
  66. X  # GCC:
  67. X! CC=gcc
  68. X! OPTIM= -g -W -Wreturn-type -Wunused -Wcomment -Wwrite-strings
  69. X! OPTIM= -W -Wreturn-type -Wunused -Wcomment -Wwrite-strings
  70. X  
  71. X  # Systems with 'cc' built from GCC (IBM RT, NeXT):
  72. X  #CC=cc
  73. X***************
  74. X*** 12,19
  75. X  #OPTIM= -g -W -Wreturn-type -Wunused -Wcomment -Wwrite-strings
  76. X  
  77. X  # Systems with 'cc' built from GCC (IBM RT, NeXT):
  78. X! CC=cc
  79. X! OPTIM=-g
  80. X  
  81. X  # Dec 3100 C compiler
  82. X  #CC=cc
  83. X
  84. X--- 13,20 -----
  85. X  OPTIM= -W -Wreturn-type -Wunused -Wcomment -Wwrite-strings
  86. X  
  87. X  # Systems with 'cc' built from GCC (IBM RT, NeXT):
  88. X! #CC=cc
  89. X! #OPTIM=-g
  90. X  
  91. X  # Dec 3100 C compiler
  92. X  #CC=cc
  93. X***************
  94. X*** 71,77
  95. X  #      -DGOD_ONLY_PCREATE -DROBOT_MODE -DRECYCLE -DNOFAKES \
  96. X  #      -DTINYHELL
  97. X  
  98. X! DEFS= -DGOD_PRIV -DCOMPRESS -DQUIET_WHISPER -DGENDER -DHOST_NAME \
  99. X        -DCONNECT_MESSAGES -DPLAYER_LIST -DDETACH -DROBOT_MODE \
  100. X        -DRECYCLE -DTINKER -DNOFAKES -DISLANDIA
  101. X  
  102. X
  103. X--- 72,78 -----
  104. X  #      -DGOD_ONLY_PCREATE -DROBOT_MODE -DRECYCLE -DNOFAKES \
  105. X  #      -DTINYHELL
  106. X  
  107. X! DEFS= -DGOD_PRIV -DCOMPRESS -DQUIET_WHISPER -DGENDER -UHOST_NAME \
  108. X        -DCONNECT_MESSAGES -DPLAYER_LIST -DDETACH -DROBOT_MODE \
  109. X        -DRECYCLE -DTINKER -DNOFAKES -UISLANDIA -DDEBUG
  110. X  
  111. X***************
  112. X*** 73,79
  113. X  
  114. X  DEFS= -DGOD_PRIV -DCOMPRESS -DQUIET_WHISPER -DGENDER -DHOST_NAME \
  115. X        -DCONNECT_MESSAGES -DPLAYER_LIST -DDETACH -DROBOT_MODE \
  116. X!       -DRECYCLE -DTINKER -DNOFAKES -DISLANDIA
  117. X  
  118. X  CFLAGS= $(OPTIM) $(DEFS)
  119. X  
  120. X
  121. X--- 74,80 -----
  122. X  
  123. X  DEFS= -DGOD_PRIV -DCOMPRESS -DQUIET_WHISPER -DGENDER -UHOST_NAME \
  124. X        -DCONNECT_MESSAGES -DPLAYER_LIST -DDETACH -DROBOT_MODE \
  125. X!       -DRECYCLE -DTINKER -DNOFAKES -UISLANDIA -DDEBUG
  126. X  
  127. X  CFLAGS= $(OPTIM) $(DEFS)
  128. X  
  129. X***************
  130. X*** 78,85
  131. X  CFLAGS= $(OPTIM) $(DEFS)
  132. X  
  133. X  # Everything needed to use db.c
  134. X! DBFILES= db.c compress.c player_list.c stringutil.c
  135. X! DBOFILES= db.o compress.o player_list.o stringutil.o
  136. X  
  137. X  # Everything except interface.c --- allows for multiple interfaces
  138. X  CFILES= create.c game.c help.c look.c match.c move.c player.c predicates.c \
  139. X
  140. X--- 79,86 -----
  141. X  CFLAGS= $(OPTIM) $(DEFS)
  142. X  
  143. X  # Everything needed to use db.c
  144. X! DBFILES= db.c compress.c player_list.c stringutil.c random.c
  145. X! DBOFILES= db.o compress.o player_list.o stringutil.o random.o
  146. X  
  147. X  # Everything except interface.c --- allows for multiple interfaces
  148. X  CFILES= create.c game.c help.c look.c match.c move.c player.c predicates.c \
  149. X***************
  150. X*** 84,90
  151. X  # Everything except interface.c --- allows for multiple interfaces
  152. X  CFILES= create.c game.c help.c look.c match.c move.c player.c predicates.c \
  153. X      rob.c set.c speech.c utils.c wiz.c game.c \
  154. X!     boolexp.c unparse.c conc.c oldinterface.c $(DBFILES)
  155. X  
  156. X  # .o versions of above
  157. X  OFILES= create.o game.o help.o look.o match.o move.o player.o predicates.o \
  158. X
  159. X--- 85,91 -----
  160. X  # Everything except interface.c --- allows for multiple interfaces
  161. X  CFILES= create.c game.c help.c look.c match.c move.c player.c predicates.c \
  162. X      rob.c set.c speech.c utils.c wiz.c game.c \
  163. X!     boolexp.c unparse.c conc.c oldinterface.c $(DBFILES) index.c rename.c
  164. X  
  165. X  # .o versions of above
  166. X  OFILES= create.o game.o help.o look.o match.o move.o player.o predicates.o \
  167. X***************
  168. X*** 89,95
  169. X  # .o versions of above
  170. X  OFILES= create.o game.o help.o look.o match.o move.o player.o predicates.o \
  171. X      rob.o set.o speech.o utils.o wiz.o boolexp.o \
  172. X!     unparse.o $(DBOFILES)
  173. X  
  174. X  # Files in the standard distribution
  175. X  DISTFILES= $(CFILES) config.h db.h externs.h interface.h match.h \
  176. X
  177. X--- 90,96 -----
  178. X  # .o versions of above
  179. X  OFILES= create.o game.o help.o look.o match.o move.o player.o predicates.o \
  180. X      rob.o set.o speech.o utils.o wiz.o boolexp.o \
  181. X!     unparse.o $(DBOFILES) index.o rename.o
  182. X  
  183. X  # Files in the standard distribution
  184. X  DISTFILES= $(CFILES) config.h db.h externs.h interface.h match.h \
  185. X***************
  186. X*** 108,114
  187. X        $(BINDIR)/dump $(BINDIR)/decompress $(BINDIR)/concentrate
  188. X  
  189. X  # paths is likely to remain broken
  190. X! all: extract sanity-check dump decompress netmud netmud.conc concentrate
  191. X  
  192. X  TAGS: *.c *.h
  193. X      etags *.c *.h
  194. X
  195. X--- 109,115 -----
  196. X        $(BINDIR)/dump $(BINDIR)/decompress $(BINDIR)/concentrate
  197. X  
  198. X  # paths is likely to remain broken
  199. X! all: extract sanity-check dump decompress fifonetmud # netmud netmud.conc concentrate
  200. X  
  201. X  TAGS: *.c *.h
  202. X      etags *.c *.h
  203. X***************
  204. X*** 117,122
  205. X      -mv -f netmud.conc netmud.conc~
  206. X      $(CC) $(CFLAGS) -o netmud.conc interface.o $(OFILES)
  207. X  
  208. X  netmud: $P oldinterface.o $(OFILES)
  209. X      -mv -f netmud netmud~
  210. X      $(CC) $(CFLAGS) -o netmud oldinterface.o $(OFILES)
  211. X
  212. X--- 118,126 -----
  213. X      -mv -f netmud.conc netmud.conc~
  214. X      $(CC) $(CFLAGS) -o netmud.conc interface.o $(OFILES)
  215. X  
  216. X+ fifonetmud: $P fifoiface.o $(OFILES)
  217. X+     $(CC) $(CFLAGS) -o $@ fifoiface.o $(OFILES)
  218. X+ match.h: copyright.h db.h
  219. X  netmud: $P oldinterface.o $(OFILES)
  220. X      -mv -f netmud netmud~
  221. X      $(CC) $(CFLAGS) -o netmud oldinterface.o $(OFILES)
  222. X===================================================================
  223. XRCS file: RCS/game.c,v
  224. Xretrieving revision 1.1
  225. Xdiff -c -r1.1 game.c
  226. X*** /tmp/,RCSt1a08638    Wed Aug  8 14:48:48 1990
  227. X--- game.c    Tue Jul 31 13:07:17 1990
  228. X***************
  229. X*** 3,9
  230. X  #include <stdio.h>
  231. X  #include <ctype.h>
  232. X  #include <signal.h>
  233. X- #include <sys/wait.h>
  234. X  #include <time.h>
  235. X  #include <stdarg.h>
  236. X      
  237. X
  238. X--- 3,8 -----
  239. X  #include <stdio.h>
  240. X  #include <ctype.h>
  241. X  #include <signal.h>
  242. X  #include <time.h>
  243. X  #include <stdarg.h>
  244. X      
  245. X***************
  246. X*** 46,51
  247. X  /* should be void, but it's defined as int */
  248. X  static int alarm_handler(void)
  249. X  {
  250. X      alarm_triggered = 1;
  251. X      if(!alarm_block) {
  252. X          fork_and_dump();
  253. X
  254. X--- 45,51 -----
  255. X  /* should be void, but it's defined as int */
  256. X  static int alarm_handler(void)
  257. X  {
  258. X+ signal(SIGALRM, SIG_IGN);
  259. X      alarm_triggered = 1;
  260. X      if(!alarm_block) {
  261. X          fork_and_dump();
  262. X***************
  263. X*** 50,55
  264. X      if(!alarm_block) {
  265. X          fork_and_dump();
  266. X      }
  267. X      return 0;
  268. X  }
  269. X  
  270. X
  271. X--- 50,56 -----
  272. X      if(!alarm_block) {
  273. X          fork_and_dump();
  274. X      }
  275. X+ signal(SIGALRM, (void (*)) alarm_handler);
  276. X      return 0;
  277. X  }
  278. X  
  279. X***************
  280. X*** 164,177
  281. X      alarm(DUMP_INTERVAL);
  282. X  }
  283. X  
  284. X- static int reaper(void)
  285. X- {
  286. X-     union wait stat;
  287. X- 
  288. X-     while(wait3(&stat, WNOHANG, 0) > 0);
  289. X-     return 0;
  290. X- }
  291. X- 
  292. X  int init_game(const char *infile, const char *outfile)
  293. X  {
  294. X     FILE *f;
  295. X
  296. X--- 165,170 -----
  297. X      alarm(DUMP_INTERVAL);
  298. X  }
  299. X  
  300. X  int init_game(const char *infile, const char *outfile)
  301. X  {
  302. X     FILE *f;
  303. X***************
  304. X*** 194,200
  305. X     dumpfile = alloc_string(outfile);
  306. X     signal(SIGALRM, (void (*)) alarm_handler);
  307. X     signal(SIGHUP, (void (*)) alarm_handler);
  308. X!    signal(SIGCHLD, (void (*)) reaper);
  309. X     alarm_triggered = 0;
  310. X     alarm(DUMP_INTERVAL);
  311. X     
  312. X
  313. X--- 187,193 -----
  314. X     dumpfile = alloc_string(outfile);
  315. X     signal(SIGALRM, (void (*)) alarm_handler);
  316. X     signal(SIGHUP, (void (*)) alarm_handler);
  317. X!    signal(SIGCLD, SIG_IGN);
  318. X     alarm_triggered = 0;
  319. X     alarm(DUMP_INTERVAL);
  320. X     
  321. SHAR_EOFxenix.diffs
  322. if test 5002 -ne "`sum < 'xenix.diffs' | sed 's/ .*//'`"
  323. then
  324.     echo shar: "possible error transmitting 'xenix.diffs'" '(sum should have been 5002)'
  325.     echo shar: "trying 'sum -r'"
  326.     if test 34058 -ne "`sum -r < 'xenix.diffs' | sed 's/ .*//'`"
  327.     then
  328.         echo shar: "probable error transmitting 'xenix.diffs'" '(sum should have been 34058)'
  329.     echo shar: "trying 'wc -c'"
  330.         if test 7297 -ne "`wc -c < 'xenix.diffs'`"
  331.         then
  332.             echo shar: "error transmitting 'xenix.diffs'" '(should have been 7297 characters)'
  333.         else
  334.             echo shar: "wc was ok"
  335.         fi
  336.     fi
  337. fi
  338. chmod 644 'xenix.diffs'
  339. fi
  340. echo shar: "extracting 'rename.c'" '(490 characters)'
  341. if test -f 'rename.c'
  342. then
  343.     echo shar: "will not over-write existing file 'rename.c'"
  344. else
  345. sed 's/^X//' << \SHAR_EOFrename.c > 'rename.c'
  346. X#include <sys/errno.h>
  347. Xint
  348. Xrename(old, new)
  349. Xchar *old, *new;
  350. X{
  351. X    extern int errno;
  352. X    int fd1,fd2;
  353. X    char buf[1024];
  354. X    int n;
  355. X    (void)unlink(new);
  356. X    if (link(old, new) == -1 && errno != EXDEV)
  357. X        return(-1);
  358. X    if((fd1=open(old,0)) == -1)
  359. X        return(-1);
  360. X    if((fd2=creat(new,0666)) == -1) {
  361. X        close(fd1);
  362. X        return(-1);
  363. X    }
  364. X    while((n=read(fd1,buf,sizeof buf)) > 0) {
  365. X        if (write(fd2,buf,n) != n) {
  366. X            close(fd1);
  367. X            close(fd2);
  368. X            unlink(new);
  369. X            return(-1);
  370. X        }
  371. X    }
  372. X    close(fd1);
  373. X    close(fd2);
  374. X    return 0;
  375. X}
  376. SHAR_EOFrename.c
  377. if test 35337 -ne "`sum < 'rename.c' | sed 's/ .*//'`"
  378. then
  379.     echo shar: "possible error transmitting 'rename.c'" '(sum should have been 35337)'
  380.     echo shar: "trying 'sum -r'"
  381.     if test 33981 -ne "`sum -r < 'rename.c' | sed 's/ .*//'`"
  382.     then
  383.         echo shar: "probable error transmitting 'rename.c'" '(sum should have been 33981)'
  384.     echo shar: "trying 'wc -c'"
  385.         if test 490 -ne "`wc -c < 'rename.c'`"
  386.         then
  387.             echo shar: "error transmitting 'rename.c'" '(should have been 490 characters)'
  388.         else
  389.             echo shar: "wc was ok"
  390.         fi
  391.     fi
  392. fi
  393. chmod 644 'rename.c'
  394. fi
  395. echo shar: "extracting 'index.c'" '(80 characters)'
  396. if test -f 'index.c'
  397. then
  398.     echo shar: "will not over-write existing file 'index.c'"
  399. else
  400. sed 's/^X//' << \SHAR_EOFindex.c > 'index.c'
  401. Xextern char *strchr();
  402. Xchar *index(s,c) char *s; int c; { return strchr(s,c); }
  403. SHAR_EOFindex.c
  404. if test 6722 -ne "`sum < 'index.c' | sed 's/ .*//'`"
  405. then
  406.     echo shar: "possible error transmitting 'index.c'" '(sum should have been 6722)'
  407.     echo shar: "trying 'sum -r'"
  408.     if test 37873 -ne "`sum -r < 'index.c' | sed 's/ .*//'`"
  409.     then
  410.         echo shar: "probable error transmitting 'index.c'" '(sum should have been 37873)'
  411.     echo shar: "trying 'wc -c'"
  412.         if test 80 -ne "`wc -c < 'index.c'`"
  413.         then
  414.             echo shar: "error transmitting 'index.c'" '(should have been 80 characters)'
  415.         else
  416.             echo shar: "wc was ok"
  417.         fi
  418.     fi
  419. fi
  420. chmod 644 'index.c'
  421. fi
  422. echo shar: "extracting 'random.c'" '(74 characters)'
  423. if test -f 'random.c'
  424. then
  425.     echo shar: "will not over-write existing file 'random.c'"
  426. else
  427. sed 's/^X//' << \SHAR_EOFrandom.c > 'random.c'
  428. Xint random() { return rand(); }
  429. Xvoid srandom(n) unsigned n; { srand(n); }
  430. SHAR_EOFrandom.c
  431. if test 6351 -ne "`sum < 'random.c' | sed 's/ .*//'`"
  432. then
  433.     echo shar: "possible error transmitting 'random.c'" '(sum should have been 6351)'
  434.     echo shar: "trying 'sum -r'"
  435.     if test 19983 -ne "`sum -r < 'random.c' | sed 's/ .*//'`"
  436.     then
  437.         echo shar: "probable error transmitting 'random.c'" '(sum should have been 19983)'
  438.     echo shar: "trying 'wc -c'"
  439.         if test 74 -ne "`wc -c < 'random.c'`"
  440.         then
  441.             echo shar: "error transmitting 'random.c'" '(should have been 74 characters)'
  442.         else
  443.             echo shar: "wc was ok"
  444.         fi
  445.     fi
  446. fi
  447. chmod 644 'random.c'
  448. fi
  449. echo shar: "extracting 'fifoiface.c'" '(27328 characters)'
  450. if test -f 'fifoiface.c'
  451. then
  452.     echo shar: "will not over-write existing file 'fifoiface.c'"
  453. else
  454. sed 's/^X//' << \SHAR_EOFfifoiface.c > 'fifoiface.c'
  455. X/*
  456. X * interface for xenix - uses fifos instead of sockets
  457. X *
  458. X * The server creates a fifo called 'fiforXXX' where XXX is replaced by the default port number.
  459. X * It then listens for a request which should be an integer, typically the process id of the client,
  460. X * and then creates two fifos named 'fiforYYY' and 'fifowYYY', where YYY is the number the client wrote
  461. X * the default fifo, for i/o to the client.  The client writes to 'fiforYYY' and reads 'fifowYYY'.
  462. X * Client code is supplied as the shell script 'tinymud.sh'.
  463. X */
  464. X#include "copyright.h"
  465. X
  466. X#undef NULL
  467. X#include <stdio.h>
  468. X#undef NULL
  469. X#include <time.h>
  470. X#include <sys/types.h>
  471. X#include <sys/file.h>
  472. X#include <sys/stat.h>
  473. X#include <sys/select.h>
  474. X#include <signal.h>
  475. X#include <sys/ioctl.h>
  476. X#include <fcntl.h>
  477. X#include <sys/errno.h>
  478. X#include <ctype.h>
  479. X
  480. X/* <netinet/in.h> */
  481. X#define u_char unsigned char
  482. X#define u_short unsigned short
  483. X#define u_long unsigned long
  484. Xstruct in_addr {
  485. X    union {
  486. X        struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
  487. X        struct { u_short s_w1,s_w2; } S_un_w;
  488. X        u_long S_addr;
  489. X    } S_un;
  490. X#define    s_addr    S_un.S_addr
  491. X};
  492. Xstruct sockaddr_in {
  493. X    short    sin_family;
  494. X    u_short    sin_port;
  495. X    struct    in_addr sin_addr;
  496. X    char    sin_zero[8];
  497. X};
  498. X#define    EWOULDBLOCK    35        /* Operation would block */
  499. X
  500. X#undef NULL
  501. X#define NULL 0
  502. X#define bzero(s,n) memset(s,'\0',n)
  503. X#define getdtablesize() FD_SETSIZE
  504. X
  505. X#include "db.h"
  506. X#include "interface.h"
  507. X#include "config.h"
  508. X
  509. Xextern int    errno;
  510. Xint    shutdown_flag = 0;
  511. X
  512. Xstatic const char *connect_fail = "Either that player does not exist, or has a different password.\n";
  513. X#ifndef REGISTRATION
  514. Xstatic const char *create_fail = "Either there is already a player with that name, or that name is illegal.\n";
  515. X#endif REGISTRATION
  516. Xstatic const char *flushed_message = "<Output Flushed>\n";
  517. Xstatic const char *shutdown_message = "Going down - Bye\n";
  518. X
  519. Xstruct text_block {
  520. X    int            nchars;
  521. X    struct text_block    *nxt;
  522. X    char            *start;
  523. X    char            *buf;
  524. X};
  525. X
  526. Xstruct text_queue {
  527. X    struct text_block *head;
  528. X    struct text_block **tail;
  529. X};
  530. X
  531. Xstruct descriptor_data {
  532. X        int rdescriptor;
  533. X        int wdescriptor;
  534. X    int connected;
  535. X    dbref player;
  536. X    char *output_prefix;
  537. X    char *output_suffix;
  538. X    int output_size;
  539. X    struct text_queue output;
  540. X    struct text_queue input;
  541. X    char *raw_input;
  542. X    char *raw_input_at;
  543. X    long last_time;
  544. X    long connected_at;
  545. X    int quota;
  546. X    struct sockaddr_in address;
  547. X    const char *hostname;        /* 5/18/90 - Fuzzy */
  548. X    struct descriptor_data *next;
  549. X    struct descriptor_data *prev;
  550. X} *descriptor_list = 0;
  551. X
  552. Xstatic int sock;
  553. Xstatic int ndescriptors = 0;
  554. X
  555. Xvoid process_commands(void);
  556. Xvoid shovechars(int port);
  557. Xvoid shutdownsock(struct descriptor_data *d);
  558. Xstruct descriptor_data *initializesock(int r, int w, struct sockaddr_in *a,
  559. X                       const char *hostname);
  560. Xvoid make_nonblocking(int s);
  561. Xvoid freeqs(struct descriptor_data *d);
  562. Xvoid welcome_user(struct descriptor_data *d);
  563. Xvoid do_motd(dbref);
  564. Xvoid check_connect(struct descriptor_data *d, const char *msg);
  565. Xvoid close_sockets();
  566. Xconst char *addrout (long);
  567. Xvoid dump_users(struct descriptor_data *d, char *user);
  568. Xvoid set_signals(void);
  569. Xstruct descriptor_data *new_connection(int sock);
  570. Xvoid parse_connect (const char *msg, char *command, char *user, char *pass);
  571. Xvoid set_userstring (char **userstring, const char *command);
  572. Xint do_command (struct descriptor_data *d, char *command);
  573. Xchar *strsave (const char *s);
  574. Xint make_socket(int);
  575. Xint queue_string(struct descriptor_data *, const char *);
  576. Xint queue_write(struct descriptor_data *, const char *, int);
  577. Xint process_output(struct descriptor_data *d);
  578. Xint process_input(struct descriptor_data *d);
  579. X#ifdef CONNECT_MESSAGES
  580. Xvoid announce_connect(dbref);
  581. Xvoid announce_disconnect(dbref);
  582. X#endif CONNECT_MESSAGES
  583. Xchar *time_format_1(long);
  584. Xchar *time_format_2(long);
  585. X
  586. X/* Signal handlers */
  587. Xint bailout (int);
  588. Xint sigshutdown (int);
  589. X#ifdef DETACH
  590. Xint logsynch (int);
  591. X#endif DETACH
  592. X
  593. Xchar *logfile = (char *)LOG_FILE;
  594. X
  595. X#define MALLOC(result, type, number) do {            \
  596. X    if (!((result) = (type *) malloc ((number) * sizeof (type))))    \
  597. X        panic("Out of memory");                \
  598. X    } while (0)
  599. X
  600. X#define FREE(x) (free((void *) x))
  601. X
  602. Xchar *fifonames[FD_SETSIZE] = {0};
  603. X
  604. Xint shutdown (s) int s;
  605. X{
  606. X    /* writelog("shutdown %d %s\n",s,fifonames[s]?fifonames[s]:"(nil)"); */
  607. X    if (fifonames[s]) {
  608. X        unlink(fifonames[s]);
  609. X        free(fifonames[s]);
  610. X        fifonames[s] = 0;
  611. X    }
  612. X    return 0;
  613. X}
  614. X#define htons(n) (n)
  615. X#define bcopy(s,t,n) memcpy(t,s,n)
  616. X
  617. Xvoid gettimeofday(tv, tz)
  618. Xstruct timeval *tv;
  619. Xstruct timezone *tz;
  620. X{
  621. X    long time();
  622. X    tv->tv_sec = time((int *)0);
  623. X}
  624. Xint select (maxd, rfds, wfds, xfds, timeout)
  625. Xint maxd;
  626. Xfd_set *rfds, *wfds, *xfds;
  627. Xstruct timeval *timeout;
  628. X{
  629. X    int maxfd,fd;
  630. X    struct stat sbuf;
  631. X    int sec = 0;
  632. X    fd_set r, w, x;
  633. X
  634. X    if (timeout) sec=timeout->tv_sec+(timeout->tv_usec+500)/1000;
  635. X    r= *rfds; w= *wfds; x= *xfds;
  636. X
  637. X    while(1) {
  638. X        *rfds=r; *wfds=w; *xfds=x;
  639. X        for(maxfd=fd=0;fd<maxd;++fd) {
  640. X            if(FD_ISSET(fd,rfds)) {
  641. X                if (stat(fifonames[fd],&sbuf) != 0)
  642. X                    goto foo;
  643. X                else if(sbuf.st_size>0)
  644. X                    ++maxfd;
  645. X                else
  646. X                    FD_CLR(fd,rfds);
  647. X            }
  648. X            if(FD_ISSET(fd,wfds)) {
  649. X                if (stat(fifonames[fd],&sbuf) != 0)
  650. X                    goto foo;
  651. X                else if(sbuf.st_size<5120)
  652. X                    ++maxfd;
  653. X                else
  654. X                    FD_CLR(fd,wfds);
  655. X            }
  656. X        }
  657. X        if(maxfd > 0 || --sec < 0) break;
  658. X        sleep(1);
  659. X    }
  660. X    return(maxfd);
  661. Xfoo:
  662. X    writelog("SELECT: %s has been unlinked!\n", fifonames[fd]);
  663. X    shutdown_flag = 1;
  664. X    return 0;
  665. X}
  666. Xchar *inet_ntoa(l) long l;
  667. X{
  668. X    static char buf[80];
  669. X    sprintf(buf,"%d.%d.%d.%d",
  670. X        (l/(256*256))%255,(l/(256*256))%255,(l/256)%255,l%255);
  671. X    return buf;
  672. X}
  673. Xint fifo(port,mode)
  674. Xint port,mode;
  675. X{
  676. X    char name[80];
  677. X    int fd = -1;
  678. X    int cmask;
  679. X    extern char *strdup();
  680. X
  681. X    sprintf(name,"fifo%c%d",mode==0?'r':'w',port);
  682. X
  683. X    unlink(name);
  684. X    cmask=umask(0);
  685. X    fd = mknod(name,0666|S_IFIFO);
  686. X    umask(cmask);
  687. X    if (fd != 0) {
  688. X        perror("mknod");
  689. X        writelog("fifo: mknod %s fail\n",name);
  690. X        fd = -1;
  691. X    }
  692. X    else if((fd = open(name,O_RDWR|O_NDELAY)) < 0) {
  693. X        perror("open fifo");
  694. X        writelog("fifo: open %s fail\n",name);
  695. X    }
  696. X    if (fd != -1) {
  697. X        if (fifonames[fd]) free(fifonames[fd]);
  698. X        fifonames[fd] = strdup(name);
  699. X    }
  700. X    return fd;
  701. X}
  702. X
  703. X#ifndef BOOLEXP_DEBUGGING
  704. Xvoid main(int argc, char **argv)
  705. X{
  706. X    if (argc < 3) {
  707. X    fprintf(stderr, "Usage: %s infile dumpfile [port [logfile]]\n", *argv);
  708. X    exit (1);
  709. X    }
  710. X
  711. X    if (argc > 4) logfile = argv[4];
  712. X
  713. X    set_signals ();
  714. X    if (init_game (argv[1], argv[2]) < 0) {
  715. X    writelog("INIT: Couldn't load %s!\n", argv[1]);
  716. X    exit (2);
  717. X    }
  718. X
  719. X    /* go do it */
  720. X    shovechars (argc >= 4 ? atoi (argv[3]) : TINYPORT);
  721. X    close_sockets ();
  722. X    dump_database ();
  723. X    exit (0);
  724. X}
  725. X#endif /*BOOLEXP_DEBUGGING*/
  726. X
  727. Xvoid set_signals(void)
  728. X{
  729. X#ifdef DETACH
  730. X    int i;
  731. X
  732. X    signal(SIGHUP, SIG_IGN);
  733. X    if (fork() != 0) exit(0);
  734. X
  735. X    for (i=getdtablesize(); i >= 0; i--)
  736. X    (void) close(i);
  737. X
  738. X    setpgrp();
  739. X    i = open("/dev/tty", O_RDWR, 0);
  740. X    if (i != -1) {
  741. X    close(i);
  742. X    }
  743. X
  744. X    freopen(logfile, "a", stderr);
  745. X    setbuf(stderr, NULL);
  746. X#endif DETACH    
  747. X    
  748. X    /* we don't care about SIGPIPE, we notice it in select() and write() */
  749. X    signal (SIGPIPE, SIG_IGN);
  750. X
  751. X    /* standard termination signals */
  752. X    signal (SIGINT, (void (*)) sigshutdown);
  753. X    signal (SIGTERM, (void (*)) sigshutdown);
  754. X
  755. X#ifdef DETACH
  756. X    /* SIGUSR2 synchronizes the log file */
  757. X    signal (SIGUSR2, (void (*)) logsynch);
  758. X#else DETACH    
  759. X    signal (SIGUSR2, (void (*)) bailout);
  760. X#endif DETACH    
  761. X
  762. X    /* catch these because we might as well */
  763. X    signal (SIGQUIT, (void (*)) bailout);
  764. X    signal (SIGILL, (void (*)) bailout);
  765. X    signal (SIGTRAP, (void (*)) bailout);
  766. X    signal (SIGIOT, (void (*)) bailout);
  767. X    signal (SIGEMT, (void (*)) bailout);
  768. X    signal (SIGFPE, (void (*)) bailout);
  769. X    signal (SIGBUS, (void (*)) bailout);
  770. X    signal (SIGSEGV, (void (*)) bailout);
  771. X    signal (SIGSYS, (void (*)) bailout);
  772. X    signal (SIGUSR1, (void (*)) bailout);
  773. X}
  774. X
  775. Xint notify(dbref player, const char *msg)
  776. X{
  777. X    struct descriptor_data *d;
  778. X    int retval = 0;
  779. X#ifdef COMPRESS
  780. X    extern const char *uncompress(const char *);
  781. X
  782. X    msg = uncompress(msg);
  783. X#endif /* COMPRESS */
  784. X
  785. X    for(d = descriptor_list; d; d = d->next) {
  786. X    if (d->connected && d->player == player) {
  787. X        queue_string(d, msg);
  788. X        queue_write(d, "\n", 1);
  789. X        retval = 1;
  790. X    }
  791. X    }
  792. X    return(retval);
  793. X}
  794. X
  795. Xstruct timeval timeval_sub(struct timeval now, struct timeval then)
  796. X{
  797. X    now.tv_sec -= then.tv_sec;
  798. X    now.tv_usec -= then.tv_usec;
  799. X    if (now.tv_usec < 0) {
  800. X    now.tv_usec += 1000000;
  801. X    now.tv_sec--;
  802. X    }
  803. X    return now;
  804. X}
  805. X
  806. Xint msec_diff(struct timeval now, struct timeval then)
  807. X{
  808. X    return ((now.tv_sec - then.tv_sec) * 1000
  809. X        + (now.tv_usec - then.tv_usec) / 1000);
  810. X}
  811. X
  812. Xstruct timeval msec_add(struct timeval t, int x)
  813. X{
  814. X    t.tv_sec += x / 1000;
  815. X    t.tv_usec += (x % 1000) * 1000;
  816. X    if (t.tv_usec >= 1000000) {
  817. X    t.tv_sec += t.tv_usec / 1000000;
  818. X    t.tv_usec = t.tv_usec % 1000000;
  819. X    }
  820. X    return t;
  821. X}
  822. X
  823. Xstruct timeval update_quotas(struct timeval last, struct timeval current)
  824. X{
  825. X    int nslices;
  826. X    struct descriptor_data *d;
  827. X
  828. X    nslices = msec_diff (current, last) / COMMAND_TIME_MSEC;
  829. X
  830. X    if (nslices > 0) {
  831. X    for (d = descriptor_list; d; d = d -> next) {
  832. X        d -> quota += COMMANDS_PER_TIME * nslices;
  833. X        if (d -> quota > COMMAND_BURST_SIZE)
  834. X        d -> quota = COMMAND_BURST_SIZE;
  835. X    }
  836. X    }
  837. X    return msec_add (last, nslices * COMMAND_TIME_MSEC);
  838. X}
  839. X
  840. Xvoid shovechars(int port)
  841. X{
  842. X    fd_set input_set, output_set;
  843. X    long now;
  844. X    struct timeval last_slice, current_time;
  845. X    struct timeval next_slice;
  846. X    struct timeval timeout, slice_timeout;
  847. X    int maxd;
  848. X    struct descriptor_data *d, *dnext;
  849. X    struct descriptor_data *newd;
  850. X    int avail_descriptors;
  851. X
  852. X    sock = make_socket (port);
  853. X    maxd = sock+1;
  854. X    gettimeofday(&last_slice, (struct timezone *) 0);
  855. X
  856. X    avail_descriptors = (getdtablesize() - 4)/2;
  857. X    
  858. X    while (shutdown_flag == 0) {
  859. X    gettimeofday(¤t_time, (struct timezone *) 0);
  860. X    last_slice = update_quotas (last_slice, current_time);
  861. X
  862. X    process_commands();
  863. X
  864. X    if (shutdown_flag)
  865. X        break;
  866. X    timeout.tv_sec = 1000;
  867. X    timeout.tv_usec = 0;
  868. X    next_slice = msec_add (last_slice, COMMAND_TIME_MSEC);
  869. X    slice_timeout = timeval_sub (next_slice, current_time);
  870. X    
  871. X    FD_ZERO (&input_set);
  872. X    FD_ZERO (&output_set);
  873. X    if (ndescriptors < avail_descriptors)
  874. X        FD_SET (sock, &input_set);
  875. X    for (d = descriptor_list; d; d=d->next) {
  876. X        if (d->input.head)
  877. X        timeout = slice_timeout;
  878. X        else
  879. X        FD_SET (d->rdescriptor, &input_set);
  880. X        if (d->output.head)
  881. X        FD_SET (d->wdescriptor, &output_set);
  882. X    }
  883. X
  884. X    if (select (maxd, &input_set, &output_set,
  885. X            (fd_set *) 0, &timeout) < 0) {
  886. X        if (errno != EINTR) {
  887. X        perror ("select");
  888. X        return;
  889. X        }
  890. X    } else {
  891. X        (void) time (&now);
  892. X        if (FD_ISSET (sock, &input_set)) {
  893. X        if (!(newd = new_connection (sock))) {
  894. X            if (errno
  895. X            && errno != EINTR
  896. X            && errno != EMFILE
  897. X            && errno != ENFILE) {
  898. X            perror ("new_connection");
  899. X            return;
  900. X            }
  901. X        } else {
  902. X        if (newd->rdescriptor >= maxd)
  903. X            maxd = newd->rdescriptor + 1;
  904. X        if (newd->wdescriptor >= maxd)
  905. X            maxd = newd->wdescriptor + 1;
  906. X        }
  907. X        }
  908. X        for (d = descriptor_list; d; d = dnext) {
  909. X        dnext = d->next;
  910. X        if (FD_ISSET (d->rdescriptor, &input_set)) {
  911. X            d->last_time = now;
  912. X            if (!process_input (d)) {
  913. X                shutdownsock (d);
  914. X                continue;
  915. X            }
  916. X        }
  917. X        if (FD_ISSET (d->wdescriptor, &output_set)) {
  918. X            if (!process_output (d)) {
  919. X            shutdownsock (d);
  920. X            }
  921. X        }
  922. X        }
  923. X    }
  924. X    }
  925. X}
  926. X
  927. Xstatic char hostname[128];
  928. X
  929. Xstruct descriptor_data *new_connection(int sock)
  930. X{
  931. X    int rnewsock, wnewsock;
  932. X    struct sockaddr_in addr;
  933. X    int addr_len;
  934. X    char buf[80];
  935. X    int n;
  936. X
  937. X    addr_len = read(sock,buf,sizeof(buf)-1);
  938. X    if (addr_len>0) {
  939. X    buf[addr_len] = '\0';
  940. X    addr.sin_addr.s_addr = n = atoi(buf);
  941. X    } else {
  942. X    return 0;
  943. X    }
  944. X
  945. X    rnewsock = fifo(n,0);
  946. X    wnewsock = fifo(n,1);
  947. X    if (rnewsock < 0 || wnewsock < 0) {
  948. X    close(rnewsock); close(wnewsock);
  949. X    return 0;
  950. X#ifdef LOCKOUT
  951. X    } else if(forbidden_site(ntohl(addr.sin_addr.s_addr))) {
  952. X    writelog("REFUSED CONNECTION from %s(%d) on descriptor %d\n",
  953. X        addrout(addr.sin_addr.s_addr),
  954. X        ntohs(addr.sin_port), newsock);
  955. X    shutdown(newsock, 2);
  956. X    close(newsock);
  957. X    errno = 0;
  958. X    return 0;
  959. X#endif /* LOCKOUT */
  960. X    } else {
  961. X    strcpy (hostname, addrout (addr.sin_addr.s_addr));
  962. X#ifdef NOISY_LOG
  963. X    writelog("ACCEPT from %s(%d) on descriptor %d\n",
  964. X         hostname,
  965. X         ntohs (addr.sin_port), newsock);
  966. X#endif NOISY_LOG
  967. X    return initializesock (rnewsock, wnewsock, &addr, hostname);
  968. X    }
  969. X}
  970. X
  971. Xconst char *addrout(long a)
  972. X{
  973. X    /* New version: returns host names, not octets.  Uses gethostbyaddr. */
  974. X    extern char *inet_ntoa(long);
  975. X    
  976. X#ifdef HOST_NAME
  977. X    struct hostent *he;
  978. X
  979. X    he = gethostbyaddr(&a,sizeof(a),AF_INET);
  980. X    if (he) return he->h_name;
  981. X    else return inet_ntoa(a);
  982. X#else
  983. X    return inet_ntoa(a);
  984. X#endif HOST_NAME
  985. X}
  986. X
  987. X
  988. Xvoid clearstrings(struct descriptor_data *d)
  989. X{
  990. X    if (d->output_prefix) {
  991. X    FREE(d->output_prefix);
  992. X    d->output_prefix = 0;
  993. X    }
  994. X    if (d->output_suffix) {
  995. X    FREE(d->output_suffix);
  996. X    d->output_suffix = 0;
  997. X    }
  998. X}
  999. X
  1000. Xvoid shutdownsock(struct descriptor_data *d)
  1001. X{
  1002. X    if (d->connected) {
  1003. X    writelog("DISCONNECT player %s(%d) %d %s\n",
  1004. X        db[d->player].name, d->player, d->rdescriptor, d->hostname);
  1005. X#ifdef CONNECT_MESSAGES
  1006. X    announce_disconnect(d->player);
  1007. X#endif CONNECT_MESSAGES
  1008. X    } else {
  1009. X    writelog("DISCONNECT descriptor %d never connected\n",
  1010. X        d->rdescriptor);
  1011. X    }
  1012. X    clearstrings (d);
  1013. X    shutdown (d->rdescriptor, 2);
  1014. X    close (d->rdescriptor);
  1015. X    shutdown (d->wdescriptor, 2);
  1016. X    close (d->wdescriptor);
  1017. X    freeqs (d);
  1018. X    if (d->prev) d->prev->next = d->next; else descriptor_list = d->next;
  1019. X    if (d->next) d->next->prev = d->prev;
  1020. X    FREE (d);
  1021. X    ndescriptors--;
  1022. X}
  1023. X
  1024. Xstruct descriptor_data *initializesock(int r, int w, struct sockaddr_in *a,
  1025. X                       const char *hostname)
  1026. X{
  1027. X    struct descriptor_data *d;
  1028. X
  1029. X    ndescriptors++;
  1030. X    MALLOC(d, struct descriptor_data, 1);
  1031. X    d->rdescriptor = r;
  1032. X    d->wdescriptor = w;
  1033. X    d->connected = 0;
  1034. X/*
  1035. X    make_nonblocking (r);
  1036. X    make_nonblocking (w);
  1037. X*/
  1038. X    d->output_prefix = 0;
  1039. X    d->output_suffix = 0;
  1040. X    d->output_size = 0;
  1041. X    d->output.head = 0;
  1042. X    d->output.tail = &d->output.head;
  1043. X    d->input.head = 0;
  1044. X    d->input.tail = &d->input.head;
  1045. X    d->raw_input = 0;
  1046. X    d->raw_input_at = 0;
  1047. X    d->quota = COMMAND_BURST_SIZE;
  1048. X    d->last_time = 0;
  1049. X    d->address = *a;            /* added 5/3/90 SCG */
  1050. X    d->hostname = alloc_string(hostname);
  1051. X    if (descriptor_list)
  1052. X        descriptor_list->prev = d;
  1053. X    d->next = descriptor_list;
  1054. X    d->prev = (struct descriptor_data *) NULL;
  1055. X    descriptor_list = d;
  1056. X    
  1057. X    welcome_user (d);
  1058. X    return d;
  1059. X}
  1060. X
  1061. Xint make_socket(int port)
  1062. X{
  1063. X    int s;
  1064. X
  1065. X    s = fifo(port,0);
  1066. X    if (s < 0) {
  1067. X    perror ("opening fifo");
  1068. X    exit (3);
  1069. X    }
  1070. X    return s;
  1071. X}
  1072. X
  1073. Xstruct text_block *make_text_block(const char *s, int n)
  1074. X{
  1075. X    struct text_block *p;
  1076. X
  1077. X    MALLOC(p, struct text_block, 1);
  1078. X    MALLOC(p->buf, char, n);
  1079. X    bcopy (s, p->buf, n);
  1080. X    p->nchars = n;
  1081. X    p->start = p->buf;
  1082. X    p->nxt = 0;
  1083. X    return p;
  1084. X}
  1085. X
  1086. Xvoid free_text_block (struct text_block *t)
  1087. X{
  1088. X    FREE (t->buf);
  1089. X    FREE ((char *) t);
  1090. X}
  1091. X
  1092. Xvoid add_to_queue(struct text_queue *q, const char *b, int n)
  1093. X{
  1094. X    struct text_block *p;
  1095. X
  1096. X    if (n == 0) return;
  1097. X
  1098. X    p = make_text_block (b, n);
  1099. X    p->nxt = 0;
  1100. X    *q->tail = p;
  1101. X    q->tail = &p->nxt;
  1102. X}
  1103. X
  1104. Xint flush_queue(struct text_queue *q, int n)
  1105. X{
  1106. X        struct text_block *p;
  1107. X    int really_flushed = 0;
  1108. X    
  1109. X    n += strlen(flushed_message);
  1110. X
  1111. X    while (n > 0 && (p = q->head)) {
  1112. X        n -= p->nchars;
  1113. X        really_flushed += p->nchars;
  1114. X        q->head = p->nxt;
  1115. X        free_text_block (p);
  1116. X    }
  1117. X    p = make_text_block(flushed_message, strlen(flushed_message));
  1118. X    p->nxt = q->head;
  1119. X    q->head = p;
  1120. X    if (!p->nxt)
  1121. X        q->tail = &p->nxt;
  1122. X    really_flushed -= p->nchars;
  1123. X    return really_flushed;
  1124. X}
  1125. X
  1126. Xint queue_write(struct descriptor_data *d, const char *b, int n)
  1127. X{
  1128. X    int space;
  1129. X
  1130. X    space = MAX_OUTPUT - d->output_size - n;
  1131. X    if (space < 0)
  1132. X        d->output_size -= flush_queue(&d->output, -space);
  1133. X    add_to_queue (&d->output, b, n);
  1134. X    d->output_size += n;
  1135. X    return n;
  1136. X}
  1137. X
  1138. Xint queue_string(struct descriptor_data *d, const char *s)
  1139. X{
  1140. X    return queue_write (d, s, strlen (s));
  1141. X}
  1142. X
  1143. Xint process_output(struct descriptor_data *d)
  1144. X{
  1145. X    struct text_block **qp, *cur;
  1146. X    int cnt;
  1147. X
  1148. X    for (qp = &d->output.head; cur = *qp;) {
  1149. X    cnt = write (d->wdescriptor, cur -> start, cur -> nchars);
  1150. X    if (cnt < 0) {
  1151. X        if (errno == EWOULDBLOCK)
  1152. X        return 1;
  1153. X        return 0;
  1154. X    }
  1155. X    d->output_size -= cnt;
  1156. X    if (cnt == cur -> nchars) {
  1157. X        if (!cur -> nxt)
  1158. X        d->output.tail = qp;
  1159. X        *qp = cur -> nxt;
  1160. X        free_text_block (cur);
  1161. X        continue;        /* do not adv ptr */
  1162. X    }
  1163. X    cur -> nchars -= cnt;
  1164. X    cur -> start += cnt;
  1165. X    break;
  1166. X    }
  1167. X    return 1;
  1168. X}
  1169. X
  1170. X/*
  1171. Xvoid make_nonblocking(int s)
  1172. X{
  1173. X    if (fcntl (s, F_SETFL, FNDELAY) == -1) {
  1174. X    perror ("make_nonblocking: fcntl");
  1175. X    panic ("FNDELAY fcntl failed");
  1176. X    }
  1177. X}
  1178. X*/
  1179. X
  1180. Xvoid freeqs(struct descriptor_data *d)
  1181. X{
  1182. X    struct text_block *cur, *next;
  1183. X
  1184. X    cur = d->output.head;
  1185. X    while (cur) {
  1186. X    next = cur -> nxt;
  1187. X    free_text_block (cur);
  1188. X    cur = next;
  1189. X    }
  1190. X    d->output.head = 0;
  1191. X    d->output.tail = &d->output.head;
  1192. X
  1193. X    cur = d->input.head;
  1194. X    while (cur) {
  1195. X    next = cur -> nxt;
  1196. X    free_text_block (cur);
  1197. X    cur = next;
  1198. X    }
  1199. X    d->input.head = 0;
  1200. X    d->input.tail = &d->input.head;
  1201. X
  1202. X    if (d->raw_input)
  1203. X        FREE (d->raw_input);
  1204. X    d->raw_input = 0;
  1205. X    d->raw_input_at = 0;
  1206. X}
  1207. X
  1208. Xvoid welcome_user(struct descriptor_data *d)
  1209. X{ 
  1210. X    queue_string (d, WELCOME_MESSAGE);
  1211. X# ifdef CONNECT_FILE
  1212. X    do_connect_msg(d, CONNECT_FILE);
  1213. X# endif
  1214. X}
  1215. X
  1216. Xvoid goodbye_user(struct descriptor_data *d)
  1217. X{
  1218. X    write (d->wdescriptor, LEAVE_MESSAGE, strlen (LEAVE_MESSAGE));
  1219. X}
  1220. X
  1221. Xchar *strsave (const char *s)
  1222. X{
  1223. X    char *p;
  1224. X
  1225. X    MALLOC (p, char, strlen(s) + 1);
  1226. X
  1227. X    if (p)
  1228. X    strcpy (p, s);
  1229. X    return p;
  1230. X}
  1231. X
  1232. Xvoid save_command (struct descriptor_data *d, const char *command)
  1233. X{
  1234. X    add_to_queue (&d->input, command, strlen(command)+1);
  1235. X}
  1236. X
  1237. Xint process_input (struct descriptor_data *d)
  1238. X{
  1239. X    char buf[1024];
  1240. X    int got;
  1241. X    char *p, *pend, *q, *qend;
  1242. X
  1243. X    got = read (d->rdescriptor, buf, sizeof buf);
  1244. X    if (got <= 0)
  1245. X    return 0;
  1246. X    if (!d->raw_input) {
  1247. X    MALLOC(d->raw_input,char,MAX_COMMAND_LEN);
  1248. X    d->raw_input_at = d->raw_input;
  1249. X    }
  1250. X    p = d->raw_input_at;
  1251. X    pend = d->raw_input + MAX_COMMAND_LEN - 1;
  1252. X    for (q=buf, qend = buf + got; q < qend; q++) {
  1253. X    if (*q == '\n') {
  1254. X        *p = '\0';
  1255. X        if (p > d->raw_input)
  1256. X        save_command (d, d->raw_input);
  1257. X        p = d->raw_input;
  1258. X    } else if (p < pend && isascii (*q) && isprint (*q)) {
  1259. X        *p++ = *q;
  1260. X    }
  1261. X    }
  1262. X    if(p > d->raw_input) {
  1263. X    d->raw_input_at = p;
  1264. X    } else {
  1265. X    FREE(d->raw_input);
  1266. X    d->raw_input = 0;
  1267. X    d->raw_input_at = 0;
  1268. X    }
  1269. X    return 1;
  1270. X}
  1271. X
  1272. Xvoid set_userstring (char **userstring, const char *command)
  1273. X{
  1274. X    if (*userstring) {
  1275. X    FREE(*userstring);
  1276. X    *userstring = 0;
  1277. X    }
  1278. X    while (*command && isascii (*command) && isspace (*command))
  1279. X    command++;
  1280. X    if (*command)
  1281. X    *userstring = strsave (command);
  1282. X}
  1283. X
  1284. Xvoid process_commands(void)
  1285. X{
  1286. X    int nprocessed;
  1287. X    struct descriptor_data *d, *dnext;
  1288. X    struct text_block *t;
  1289. X
  1290. X    do {
  1291. X    nprocessed = 0;
  1292. X    for (d = descriptor_list; d; d = dnext) {
  1293. X        dnext = d->next;
  1294. X        if (d -> quota > 0 && (t = d -> input.head)) {
  1295. X        d -> quota--;
  1296. X        nprocessed++;
  1297. X        if (!do_command (d, t -> start)) {
  1298. X            shutdownsock (d);
  1299. X        } else {
  1300. X            d -> input.head = t -> nxt;
  1301. X            if (!d -> input.head)
  1302. X            d -> input.tail = &d -> input.head;
  1303. X            free_text_block (t);
  1304. X        }
  1305. X        }
  1306. X    }
  1307. X    } while (nprocessed > 0);
  1308. X}
  1309. X
  1310. Xint do_command (struct descriptor_data *d, char *command)
  1311. X{
  1312. X    if (!strcmp (command, QUIT_COMMAND)) {
  1313. X    goodbye_user (d);
  1314. X    return 0;
  1315. X    } else if (!strncmp (command, WHO_COMMAND, strlen(WHO_COMMAND))) {
  1316. X    if (d->output_prefix) {
  1317. X        queue_string (d, d->output_prefix);
  1318. X        queue_write (d, "\n", 1);
  1319. X    }
  1320. X    dump_users (d, command + strlen(WHO_COMMAND));
  1321. X    if (d->output_suffix) {
  1322. X        queue_string (d, d->output_suffix);
  1323. X        queue_write (d, "\n", 1);
  1324. X    }
  1325. X    } else if (d->connected &&
  1326. X           !strncmp (command, PREFIX_COMMAND, strlen (PREFIX_COMMAND))) {
  1327. X#ifdef ROBOT_MODE
  1328. X    if (!Robot(d->player)) { 
  1329. X#ifndef TINKER
  1330. X        notify(d->player,
  1331. X           "Only robots can use OUTPUTPREFIX; contact a Wizard.");
  1332. X#else TINKER
  1333. X        notify(d->player,
  1334. X           "Only robots can use OUTPUTPREFIX; contact a Tinker.");
  1335. X#endif TINKER
  1336. X        return 1;
  1337. X    }
  1338. X    if (!d->connected) return 1;
  1339. X#endif ROBOT_MODE
  1340. X    set_userstring (&d->output_prefix, command+strlen(PREFIX_COMMAND));
  1341. X    } else if (d->connected &&
  1342. X           !strncmp (command, SUFFIX_COMMAND, strlen (SUFFIX_COMMAND))) {
  1343. X#ifdef ROBOT_MODE
  1344. X    if (!Robot(d->player)) { 
  1345. X#ifndef TINKER
  1346. X        notify(d->player,
  1347. X           "Only robots can use OUTPUTSUFFIX; contact a Wizard.");
  1348. X#else TINKER
  1349. X        notify(d->player,
  1350. X           "Only robots can use OUTPUTSUFFIX; contact a Tinker.");
  1351. X#endif TINKER
  1352. X        return 1;
  1353. X    }
  1354. X#endif ROBOT_MODE
  1355. X    set_userstring (&d->output_suffix, command+strlen(SUFFIX_COMMAND));
  1356. X    } else {
  1357. X    if (d->connected) {
  1358. X        if (d->output_prefix) {
  1359. X        queue_string (d, d->output_prefix);
  1360. X        queue_write (d, "\n", 1);
  1361. X        }
  1362. X        process_command (d->player, command);
  1363. X        if (d->output_suffix) {
  1364. X        queue_string (d, d->output_suffix);
  1365. X        queue_write (d, "\n", 1);
  1366. X        }
  1367. X    } else {
  1368. X        check_connect (d, command);
  1369. X    }
  1370. X    }
  1371. X    return 1;
  1372. X}
  1373. X
  1374. Xvoid check_connect (struct descriptor_data *d, const char *msg)
  1375. X{
  1376. X    char command[MAX_COMMAND_LEN];
  1377. X    char user[MAX_COMMAND_LEN];
  1378. X    char password[MAX_COMMAND_LEN];
  1379. X    dbref player;
  1380. X
  1381. X    parse_connect (msg, command, user, password);
  1382. X
  1383. X    if (!strncmp (command, "co", 2)) {
  1384. X    player = connect_player (user, password);
  1385. X    if (player == NOTHING) {
  1386. X        queue_string (d, connect_fail);
  1387. X        writelog("FAILED CONNECT %s on %d %s\n",
  1388. X             user, d->rdescriptor, d->hostname);
  1389. X    } else {
  1390. X        writelog("CONNECTED %s(%d) on %d %s\n",
  1391. X             db[player].name, player, d->rdescriptor, d->hostname);
  1392. X        d->connected = 1;
  1393. X        d->connected_at = time(NULL);
  1394. X        d->player = player;
  1395. X
  1396. X        do_motd (player);
  1397. X        do_look_around (player);
  1398. X#ifdef CONNECT_MESSAGES
  1399. X        announce_connect(player);
  1400. X#endif CONNECT_MESSAGES
  1401. X    }
  1402. X    } else if (!strncmp (command, "cr", 2)) {
  1403. X#ifndef REGISTRATION    
  1404. X    player = create_player (user, password);
  1405. X    if (player == NOTHING) {
  1406. X        queue_string (d, create_fail);
  1407. X        writelog("FAILED CREATE %s on %d %s\n",
  1408. X             user, d->rdescriptor, d->hostname);
  1409. X    } else {
  1410. X        writelog("CREATED %s(%d) on descriptor %d %s\n",
  1411. X             db[player].name, player, d->rdescriptor, d->hostname);
  1412. X        d->connected = 1;
  1413. X        d->connected_at = time(NULL);
  1414. X        d->player = player;
  1415. X
  1416. X        do_motd (player);
  1417. X        do_look_around (player);
  1418. X#ifdef CONNECT_MESSAGES
  1419. X        announce_connect(player);
  1420. X#endif CONNECT_MESSAGES
  1421. X    }
  1422. X#else
  1423. X    queue_string (d, REGISTER_MESSAGE);
  1424. X#endif REGISTRATION    
  1425. X    } else {
  1426. X    welcome_user (d);
  1427. X    }
  1428. X}
  1429. X
  1430. Xvoid parse_connect (const char *msg, char *command, char *user, char *pass)
  1431. X{
  1432. X    char *p;
  1433. X
  1434. X    while (*msg && isascii(*msg) && isspace (*msg))
  1435. X    msg++;
  1436. X    p = command;
  1437. X    while (*msg && isascii(*msg) && !isspace (*msg))
  1438. X    *p++ = *msg++;
  1439. X    *p = '\0';
  1440. X    while (*msg && isascii(*msg) && isspace (*msg))
  1441. X    msg++;
  1442. X    p = user;
  1443. X    while (*msg && isascii(*msg) && !isspace (*msg))
  1444. X    *p++ = *msg++;
  1445. X    *p = '\0';
  1446. X    while (*msg && isascii(*msg) && isspace (*msg))
  1447. X    msg++;
  1448. X    p = pass;
  1449. X    while (*msg && isascii(*msg) && !isspace (*msg))
  1450. X    *p++ = *msg++;
  1451. X    *p = '\0';
  1452. X}
  1453. X
  1454. Xvoid close_sockets(void)
  1455. X{
  1456. X    struct descriptor_data *d, *dnext;
  1457. X
  1458. X    for (d = descriptor_list; d; d = dnext) {
  1459. X    dnext = d->next;
  1460. X    write (d->wdescriptor, shutdown_message, strlen (shutdown_message));
  1461. X    if (shutdown (d->rdescriptor, 2) < 0)
  1462. X        perror ("shutdown");
  1463. X    close (d->rdescriptor);
  1464. X    if (shutdown (d->wdescriptor, 2) < 0)
  1465. X        perror ("shutdown");
  1466. X    close (d->wdescriptor);
  1467. X    }
  1468. X    close (sock);
  1469. X}
  1470. X
  1471. Xvoid emergency_shutdown(void)
  1472. X{
  1473. X    close_sockets();
  1474. X}
  1475. X
  1476. Xvoid boot_off(dbref player)
  1477. X{
  1478. X    struct descriptor_data *d, *dnext;
  1479. X    for (d = descriptor_list; d; d = dnext) {
  1480. X      dnext = d->next;
  1481. X      if (d->connected && d->player == player) {
  1482. X          process_output(d);
  1483. X      shutdownsock(d);
  1484. X      }
  1485. X    }
  1486. X}
  1487. X
  1488. Xint bailout (int sig)
  1489. X{
  1490. X    writelog("BAILOUT: caught signal %d\n", sig);
  1491. X    panic("PANIC on spurious signal");
  1492. X    _exit(7);
  1493. X    return 0;
  1494. X}
  1495. X
  1496. Xint sigshutdown (int sig)
  1497. X{
  1498. X    writelog("SHUTDOWN: on signal %d\n", sig);
  1499. X    shutdown_flag = 1;
  1500. X    return 0;
  1501. X}
  1502. X
  1503. X#ifdef DETACH
  1504. Xint logsynch (int sig)
  1505. X{
  1506. X    freopen(logfile, "a", stderr);
  1507. X    setbuf(stderr, NULL);
  1508. X    writelog("log file reopened\n");
  1509. X    return 0;
  1510. X}
  1511. X#endif DETACH    
  1512. X
  1513. Xvoid dump_users(struct descriptor_data *e, char *user)
  1514. X{
  1515. X    struct descriptor_data *d;
  1516. X    long now;
  1517. X    char buf[1024];
  1518. X    int wizard;
  1519. X    int reversed, tabular;
  1520. X
  1521. X    while (*user && isspace(*user)) user++;
  1522. X    if (!*user) user = NULL;
  1523. X
  1524. X    reversed = e->connected && Flag(e->player,REVERSED_WHO);
  1525. X    tabular = e->connected && Flag(e->player,TABULAR_WHO);
  1526. X
  1527. X    (void) time (&now);
  1528. X    queue_string(e,
  1529. X         tabular ? "Player Name          On For Idle\n" : "Current Players:\n");
  1530. X#ifdef GOD_MODE
  1531. X    wizard = e->connected && God(e->player);
  1532. X#else GOD_MODE    
  1533. X    wizard = e->connected && Wizard(e->player);
  1534. X#endif GOD_MODE
  1535. X
  1536. X    d = descriptor_list;
  1537. X    
  1538. X    if (reversed)
  1539. X    while (d && d->next) d = d->next;
  1540. X
  1541. X    while (d) {
  1542. X    if (d->connected &&
  1543. X        (!user || string_prefix(db[d->player].name, user))) {
  1544. X        if (tabular) {
  1545. X        sprintf(buf,"%-16s %10s %4s",
  1546. X            db[d->player].name,
  1547. X            time_format_1(now - d->connected_at),
  1548. X            time_format_2(now - d->last_time));
  1549. X        if (wizard) 
  1550. X            sprintf(buf+strlen(buf),
  1551. X                " %s", d->hostname);
  1552. X        } else {
  1553. X        sprintf(buf,
  1554. X            "%s idle %d seconds",
  1555. X            db[d->player].name,
  1556. X            now - d->last_time);
  1557. X        if (wizard) 
  1558. X            sprintf(buf+strlen(buf),
  1559. X                " from host %s", d->hostname);
  1560. X        }
  1561. X        strcat(buf,"\n");
  1562. X        queue_string (e, buf);
  1563. X    }
  1564. X    if (reversed) d = d->prev; else d = d->next;
  1565. X    }
  1566. X}
  1567. X
  1568. Xchar *time_format_1(long dt)
  1569. X{
  1570. X    register struct tm *delta;
  1571. X    static char buf[64];
  1572. X    
  1573. X    delta = gmtime(&dt);
  1574. X    if (delta->tm_yday > 0)
  1575. X    sprintf(buf, "%dd %02d:%02d",
  1576. X        delta->tm_yday, delta->tm_hour, delta->tm_min);
  1577. X    else
  1578. X    sprintf(buf, "%02d:%02d",
  1579. X        delta->tm_hour, delta->tm_min);
  1580. X    return buf;
  1581. X}
  1582. X
  1583. Xchar *time_format_2(long dt)
  1584. X{
  1585. X    register struct tm *delta;
  1586. X    static char buf[64];
  1587. X    
  1588. X    delta = gmtime(&dt);
  1589. X    if (delta->tm_yday > 0)
  1590. X    sprintf(buf, "%dd", delta->tm_yday);
  1591. X    else if (delta->tm_hour > 0)
  1592. X    sprintf(buf, "%dh", delta->tm_hour);
  1593. X    else if (delta->tm_min > 0)
  1594. X    sprintf(buf, "%dm", delta->tm_min);
  1595. X    else
  1596. X    sprintf(buf, "%ds", delta->tm_sec);
  1597. X    return buf;
  1598. X}
  1599. X
  1600. X#ifdef CONNECT_MESSAGES
  1601. Xvoid announce_connect(dbref player)
  1602. X{
  1603. X    dbref loc;
  1604. X    char buf[BUFFER_LEN];
  1605. X
  1606. X    if ((loc = getloc(player)) == NOTHING) return;
  1607. X    if (Dark(player) || Dark(loc)) return;
  1608. X
  1609. X    sprintf(buf, "%s has connected.", db[player].name);
  1610. X
  1611. X    notify_except(db[loc].contents, player, buf);
  1612. X}
  1613. X
  1614. Xvoid announce_disconnect(dbref player)
  1615. X{
  1616. X    dbref loc;
  1617. X    char buf[BUFFER_LEN];
  1618. X
  1619. X    if ((loc = getloc(player)) == NOTHING) return;
  1620. X    if (Dark(player) || Dark(loc)) return;
  1621. X
  1622. X    sprintf(buf, "%s has disconnected.", db[player].name);
  1623. X
  1624. X    notify_except(db[loc].contents, player, buf);
  1625. X}
  1626. X#endif CONNECT_MESSAGES
  1627. Xint do_connect_msg(struct descriptor_data * d, const char *filename)
  1628. X{
  1629. X  FILE           *f;
  1630. X  char            buf[BUFFER_LEN];
  1631. X
  1632. X  if ((f = fopen(filename, "r")) == (FILE *)NULL)
  1633. X  {
  1634. X    return (0);
  1635. X  } else
  1636. X  {
  1637. X    while (fgets(buf, sizeof buf, f))
  1638. X    {
  1639. X      queue_string(d, (char *)buf);
  1640. X
  1641. X    }
  1642. X    fclose(f);
  1643. X    return (1);
  1644. X  }
  1645. X}
  1646. SHAR_EOFfifoiface.c
  1647. if test 47081 -ne "`sum < 'fifoiface.c' | sed 's/ .*//'`"
  1648. then
  1649.     echo shar: "possible error transmitting 'fifoiface.c'" '(sum should have been 47081)'
  1650.     echo shar: "trying 'sum -r'"
  1651.     if test 31121 -ne "`sum -r < 'fifoiface.c' | sed 's/ .*//'`"
  1652.     then
  1653.         echo shar: "probable error transmitting 'fifoiface.c'" '(sum should have been 31121)'
  1654.     echo shar: "trying 'wc -c'"
  1655.         if test 27328 -ne "`wc -c < 'fifoiface.c'`"
  1656.         then
  1657.             echo shar: "error transmitting 'fifoiface.c'" '(should have been 27328 characters)'
  1658.         else
  1659.             echo shar: "wc was ok"
  1660.         fi
  1661.     fi
  1662. fi
  1663. chmod 644 'fifoiface.c'
  1664. fi
  1665. echo shar: "extracting 'tinymud.sh'" '(764 characters)'
  1666. if test -f 'tinymud.sh'
  1667. then
  1668.     echo shar: "will not over-write existing file 'tinymud.sh'"
  1669. else
  1670. sed 's/^X//' << \SHAR_EOFtinymud.sh > 'tinymud.sh'
  1671. X:
  1672. X# tinymud client
  1673. Xport=4201
  1674. Xcd /usr/local/games/lib/netmud
  1675. Xtest -p fifor$port || { echo "no server fifo";exit 1; }
  1676. Xpid=$$
  1677. Xecho $pid >> fifor$port
  1678. Xecho "connecting...\c"
  1679. Xtries=30
  1680. Xwhile test $tries -gt 0
  1681. Xdo
  1682. X    sleep 1
  1683. X    test -p fifor$pid -a -p fifow$pid && break
  1684. X    tries=`expr $tries - 1`
  1685. Xdone
  1686. Xecho
  1687. Xtest $tries -eq 0 && { echo "$0: timeout waiting for server";exit 1; }
  1688. Xtrap '' 0 1 2 3 15
  1689. Xcat -u fifow$pid &
  1690. Xchild=$!
  1691. Xcleanup() {
  1692. X    kill $child 2>/dev/null
  1693. X    test -p fifor$pid && echo QUIT >> fifor$pid
  1694. X    rm -f fifor$pid
  1695. X}
  1696. Xtrap 'cleanup; exit' 0
  1697. Xtrap 'exit' 1 2 3 15
  1698. Xwhile test -p fifor$pid -a -p fifow$pid && read x
  1699. Xdo
  1700. X    case "$x" in
  1701. X    +x) set +x;;
  1702. X    -x) set -x;;
  1703. X    !) sh -i;echo "\n$0";;
  1704. X    *) test -p fifor$pid || break
  1705. X       echo "$x" >> fifor$pid
  1706. X       sleep 1
  1707. X       ;;
  1708. X    esac
  1709. Xdone
  1710. SHAR_EOFtinymud.sh
  1711. if test 59606 -ne "`sum < 'tinymud.sh' | sed 's/ .*//'`"
  1712. then
  1713.     echo shar: "possible error transmitting 'tinymud.sh'" '(sum should have been 59606)'
  1714.     echo shar: "trying 'sum -r'"
  1715.     if test 34991 -ne "`sum -r < 'tinymud.sh' | sed 's/ .*//'`"
  1716.     then
  1717.         echo shar: "probable error transmitting 'tinymud.sh'" '(sum should have been 34991)'
  1718.     echo shar: "trying 'wc -c'"
  1719.         if test 764 -ne "`wc -c < 'tinymud.sh'`"
  1720.         then
  1721.             echo shar: "error transmitting 'tinymud.sh'" '(should have been 764 characters)'
  1722.         else
  1723.             echo shar: "wc was ok"
  1724.         fi
  1725.     fi
  1726. fi
  1727. chmod 644 'tinymud.sh'
  1728. fi
  1729. echo shar: "extracting 'restart'" '(381 characters)'
  1730. if test -f 'restart'
  1731. then
  1732.     echo shar: "will not over-write existing file 'restart'"
  1733. else
  1734. sed 's/^X//' << \SHAR_EOFrestart > 'restart'
  1735. X:
  1736. Xumask 002
  1737. Xport=4201
  1738. XS=/u2/src/games/tinymud/src
  1739. XL=/usr/local/games/lib/netmud
  1740. Xnetmud=$S/fifonetmud
  1741. Xcd $L
  1742. X
  1743. Xmv tinymud.db tinymud.db.old 2>/dev/null
  1744. Xif test -f tinymud.db.new; then
  1745. X    mv tinymud.db.new tinymud.db
  1746. Xelse
  1747. X    cp tinymud.db.old tinymud.db
  1748. Xfi
  1749. Xrm -f fifo*
  1750. Xecho RESTARTED AT `date` >> tinymud.log
  1751. X# ignore hup
  1752. Xtrap '' 1
  1753. Xexec $netmud tinymud.db tinymud.db.new $port tinymud.log
  1754. SHAR_EOFrestart
  1755. if test 32991 -ne "`sum < 'restart' | sed 's/ .*//'`"
  1756. then
  1757.     echo shar: "possible error transmitting 'restart'" '(sum should have been 32991)'
  1758.     echo shar: "trying 'sum -r'"
  1759.     if test 22561 -ne "`sum -r < 'restart' | sed 's/ .*//'`"
  1760.     then
  1761.         echo shar: "probable error transmitting 'restart'" '(sum should have been 22561)'
  1762.     echo shar: "trying 'wc -c'"
  1763.         if test 381 -ne "`wc -c < 'restart'`"
  1764.         then
  1765.             echo shar: "error transmitting 'restart'" '(should have been 381 characters)'
  1766.         else
  1767.             echo shar: "wc was ok"
  1768.         fi
  1769.     fi
  1770. fi
  1771. chmod 755 'restart'
  1772. fi
  1773. exit 0
  1774. #    End of shell archive
  1775.